﻿using SIE.SCADA.Common.Log;
using SIE.SCADA.Helper;
using SIE.SCADA.StationDemo.Abstract;
using SIE.SCADA.StationDemo.Common;
#if NETSTANDARD2_0
using SIE.SCADA.IOCore.Channel.Serial;
#endif
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Text;
using System.Threading;

namespace SIE.SCADA.StationDemo.SerialCommunicat
{
    class SignalLight: WorkerBase
    {

        //01 06 00 10 00 08 89 C9 蜂鸣器
        //01 06 00 10 00 09 48 09 蜂鸣器+红灯
        //01 06 00 10 00 0A 08 08 蜂鸣器+黄灯
        //01 06 00 10 00 0C 88 0A 蜂鸣器+绿灯




        private readonly byte[] OffCmd = { 0x01, 0x06, 0x00, 0x10, 0x00, 0x00, 0x88, 0x0F }; //全关
        private readonly byte[] RedCmd =         { 0x01, 0x06, 0x00, 0x10, 0x00, 0x01, 0x49, 0xCF }; //红灯
        private readonly byte[] YellCmd ={ 0x01, 0x06, 0x00, 0x10, 0x00, 0x02, 0x09, 0xCE };    //黄灯
        private readonly byte[] GreCmd =         { 0x01, 0x06, 0x00, 0x10, 0x00, 0x04, 0x89, 0xCC }; //绿灯
        private readonly byte[] RedAndAlarmCmd = { 0x01, 0x06, 0x00, 0x10, 0x00, 0x09, 0x48, 0x09 }; //蜂鸣器+红灯


        private readonly int baudRate = 9600;
        private string _portName;
        private Queue<Color> light_queue;
        private AdvancedThread _thread;
        private Color _lastColor = Color.Off;

#if NETSTANDARD2_0
        private LinuxSerialPort csp = null;
#else
        private SerialPort csp = null;
#endif

        public override bool IsRunning { get; set; }

        public SignalLight(string portName)
        {
            _portName = portName;
            light_queue = new Queue<Color>();
            _thread = new AdvancedThread(ShowLight,1);
            _thread.Start();
        }

        public override void Stop()
        {
            try
            {
                _thread?.Stop();
                csp?.Write(OffCmd, 0, OffCmd.Length);
                ClosePort();
            }
            catch (Exception ex)
            {
                Logger.Error($"串口退出失败{ex.Message}");
            }
        }

        public void Add(Color color)
        {
            light_queue.Enqueue(color);
        }

        private void ShowLight()
        {
            try
            {
                if (light_queue == null ||light_queue.Count == 0) return;
                var color = light_queue.Dequeue();
                //Logger.Info($"指示灯状态提示:{color.ToString()}");
                if (_lastColor != color)
                {
                    switch (color)
                    {
                        case Color.Off:
                            WritePort(OffCmd);
                            break;
                        case Color.Green:
                            WritePort(GreCmd);
                            break;
                        case Color.Red:
                            WritePort(RedCmd);
                            break;
                        case Color.Yellow:
                            WritePort(YellCmd);
                            break;
                        case Color.RedAndAlarm:
                            WritePort(RedAndAlarmCmd);
                            break;
                    }
                    _lastColor = color;
                }
            }
            catch (Exception ex)
            {
                Logger.Error($"指示灯输出失败!{ex.Message}");
            }
            finally
            {
                Thread.Sleep(200);
            }
        }

        private void WritePort(byte[] cmd)
        {
            try
            {
                if (csp.IsOpen)
                {
                    string str = string.Empty;
                    foreach (var item in cmd)
                    {
                        str += item.ToString();
                        str += " ";
                    }
                    Logger.Info($"指示灯输出{str}");
                    csp?.Write(cmd, 0, cmd.Length);
                }
            }
            catch (Exception ex)
            {
                Logger.Error($"指示灯输出失败{ex.Message}");
            }
        }

        protected override bool Init()
        {
            return true;
        }

        protected override bool Load()
        {
            return true;
        }

        private void ClosePort()
        {
            if(csp != null)
            {
                if(csp.IsOpen)
                    csp.Dispose();
                csp = null;
            }
            Logger.Info($"close serial port:{_portName} succful!");
        }

        public override void Start()
        {
            ClosePort();
#if NETSTANDARD2_0
            csp = new LinuxSerialPort(_portName, baudRate);
#else
            csp = new SerialPort(_portName, baudRate);
#endif
            try
            {
                csp.Open();
                Thread.Sleep(800);
                Logger.Info($"Service Open Uart [{_portName}] Succful!");
            }
            catch (Exception ex)
            {
                Logger.Info($"RunService Open Uart [{_portName}] Exception:{ex}");
            }
        }

        //在串口通讯过程中，经常要用到 16进制与字符串、字节数组之间的转换
        public static byte[] HexStringToBytes(string hs)
        {
            string[] strArr = hs.Trim().Split(' ');
            byte[] b = new byte[strArr.Length];
            //逐个字符变为16进制字节数据
            for (int i = 0; i < strArr.Length; i++)
            {
                b[i] = Convert.ToByte(strArr[i], 16);
            }
            //按照指定编码将字节数组变为字符串
            return b;
        }
    }
}
